package com.yf.repo.modules.repo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.base.api.api.dto.PagingReqDTO;
import com.yf.base.api.exception.ServiceException;
import com.yf.base.enums.OpenType;
import com.yf.base.utils.BeanMapper;
import com.yf.repo.modules.qu.dto.QuDTO;
import com.yf.repo.modules.qu.dto.request.QuQueryReqDTO;
import com.yf.repo.modules.qu.service.QuService;
import com.yf.repo.modules.repo.dto.RepoDTO;
import com.yf.repo.modules.repo.dto.ext.ChapterExtDTO;
import com.yf.repo.modules.repo.dto.ext.RepoDetailDTO;
import com.yf.repo.modules.repo.dto.ext.RepoTypeCountDTO;
import com.yf.repo.modules.repo.dto.request.RepoReqDTO;
import com.yf.repo.modules.repo.dto.response.ChapterGroupDTO;
import com.yf.repo.modules.repo.dto.response.LevelGroupDTO;
import com.yf.repo.modules.repo.dto.response.TypeGroupDTO;
import com.yf.repo.modules.repo.entity.Repo;
import com.yf.repo.modules.repo.entity.RepoDepart;
import com.yf.repo.modules.repo.mapper.RepoMapper;
import com.yf.repo.modules.repo.service.RepoChapterService;
import com.yf.repo.modules.repo.service.RepoDepartService;
import com.yf.repo.modules.repo.service.RepoPersonService;
import com.yf.repo.modules.repo.service.RepoService;
import com.yf.system.modules.user.UserUtils;
import com.yf.system.modules.user.entity.SysUser;
import com.yf.system.modules.user.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* <p>
* 语言设置 服务实现类
* </p>
*
* @author 聪明笨狗
* @since 2020-05-25 13:23
*/
@Service
public class RepoServiceImpl extends ServiceImpl<RepoMapper, Repo> implements RepoService {

    @Autowired
    private RepoChapterService repoChapterService;

    @Autowired
    private RepoPersonService repoPersonService;

    @Autowired
    private RepoDepartService repoDepartService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private QuService quService;

    @Override
    public IPage<RepoDetailDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO) {
        // 创建分页对象
        Page query = reqDTO.toPage();

        //查询条件
        QueryWrapper<Repo> wrapper = new QueryWrapper<>();

        // 请求参数
        RepoReqDTO params = reqDTO.getParams();

        if (params != null) {
            // 分类 ID
            if (params.getCatId() != null) {
                wrapper.lambda().eq(Repo::getCatId, params.getCatId());
            }
            // 题库名称
            if (!StringUtils.isBlank(params.getTitle())) {
                wrapper.lambda().like(Repo::getTitle, params.getTitle());
            }
        }
        // 权限逻辑
        String currentUserId = UserUtils.getUserId();
        // 获取用户部门
        SysUser sysUser = sysUserService.getById(currentUserId);
        String deptCode = sysUser.getDeptCode();
        // 根据部门查找仓库部门映射
        List<RepoDepart> repoDepartList = repoDepartService.list(
                new QueryWrapper<RepoDepart>().eq("dept_code", deptCode));
        // 获取仓库 id
        List<String> repoId = repoDepartList.stream()
                .map(RepoDepart::getRepoId)
                .collect(Collectors.toList());
        // 管理员
        boolean isAdmin = UserUtils.getRoleLevel() > 3;
        if (isAdmin) {
            // 如果是管理员，并且自己写了查询条件，按照查询条件找
            if (params != null && !StringUtils.isBlank(params.getCreateBy())) {
                wrapper.eq("create_by", params.getCreateBy());
            }
        } else {
            // 用部门代码过滤普通用户数据
            // 直接查 deptCode 是按照 el_repo 查
            if (repoId != null && !repoId.isEmpty()) {
                wrapper.in("id", repoId);
            } else {
                return new Page<>();
            }
        }
        // 按更新时间倒序
        wrapper.lambda().orderByDesc(Repo::getUpdateTime);

        IPage<Repo> page = this.page(query, wrapper);

        IPage<RepoDetailDTO> pageData = new Page<>();
        pageData.setCurrent(page.getCurrent());
        pageData.setSize(page.getSize());
        pageData.setTotal(page.getTotal());
        
        // 优化：批量查询题型统计，避免N+1查询问题
        List<Repo> repoList = page.getRecords();
        if (CollectionUtils.isEmpty(repoList)) {
            pageData.setRecords(new ArrayList<>());
            return pageData;
        }
        
        // 提取所有题库ID
        List<String> repoIds = repoList.stream()
                .map(Repo::getId)
                .collect(Collectors.toList());
        
        // 批量查询所有题库的题型统计
        List<RepoTypeCountDTO> allTypeList = baseMapper.findTypeListBatch(repoIds);
        
        // 按题库ID分组
        Map<String, List<RepoTypeCountDTO>> typeListMap = allTypeList.stream()
                .collect(Collectors.groupingBy(RepoTypeCountDTO::getRepoId));
        
        // 构建结果
        pageData.setRecords(
                repoList.stream().map(repo -> {
                    RepoDetailDTO dto = new RepoDetailDTO();
                    BeanUtils.copyProperties(repo, dto);
                    // 从批量查询结果中获取该题库的题型统计
                    List<RepoTypeCountDTO> typeList = typeListMap.getOrDefault(repo.getId(), new ArrayList<>());
                    dto.setTypeList(typeList);
                    return dto;
                }).collect(Collectors.toList())
        );
        return pageData;

//        return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams());
    }

    @Override
    public IPage<RepoDetailDTO> userPaging(PagingReqDTO<RepoReqDTO> reqDTO) {
        return baseMapper.userPaging(reqDTO.toPage(), reqDTO.getParams());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(RepoDetailDTO reqDTO) {

        String tempId = reqDTO.getId();
        if(tempId.startsWith("temp_")){
            reqDTO.setId(null);
        }

        // 复制参数
        Repo entity = new Repo();
        BeanMapper.copy(reqDTO, entity);
        this.saveOrUpdate(entity);

        // 保存章节信息
        repoChapterService.saveAll(entity.getId(), reqDTO.getChapters());


        // 人员列表
        if(OpenType.PERSON.equals(entity.getOpenType())) {
            repoPersonService.modifyAll(tempId, entity.getId());
        }

        // 部门列表
        if(OpenType.DEPART.equals(entity.getOpenType())) {
            repoDepartService.saveAll(entity.getId(), reqDTO.getDeptCodes());
        }
    }

    @Override
    public RepoDetailDTO detail(String id) {

        // 基础信息
        RepoDetailDTO respDTO = baseMapper.detail(id);

        if(respDTO == null){
            throw new ServiceException("啊哦，题库走丢了！");
        }


        // 部门列表
        if(OpenType.DEPART.equals(respDTO.getOpenType())) {
            List<String> list = repoDepartService.listAll(id);
            respDTO.setDeptCodes(list);
        }

        // 填充章节信息
        List<ChapterExtDTO> list = repoChapterService.listByRepo(id);
        respDTO.setChapters(list);

        // 是否购买
        respDTO.setIsBuy(true);

        return respDTO;
    }

    @Override
    public List<TypeGroupDTO> findTypeGroup(QuDTO reqDTO){
        return baseMapper.findTypeGroup(reqDTO);
    }

    @Override
    public List<ChapterGroupDTO> findChapterGroup(QuQueryReqDTO query) {

        // 响应列表
        List<ChapterGroupDTO> respList = new ArrayList<>();

        // 首先查找未分章节的题目
        List<LevelGroupDTO> nullList = baseMapper.findNullChapterList(query);
        if(!CollectionUtils.isEmpty(nullList)){
            ChapterGroupDTO dto = new ChapterGroupDTO();
            dto.setQuType(query.getQuType());
            dto.setChapterId("");
            dto.setTitle("未分章节题目");
            dto.setLevels(nullList);
            respList.add(dto);
        }

        // 再查询已经分章节的
        List<ChapterExtDTO> chapterList = repoChapterService.listByRepo(query.getRepoId());
        if(CollectionUtils.isEmpty(chapterList)){
            return respList;
        }

        for(ChapterExtDTO chapter: chapterList){
            ChapterGroupDTO group = new ChapterGroupDTO();
            group.setQuType(query.getQuType());
            group.setRepoId(query.getRepoId());
            group.setTitle(chapter.getTitle());
            group.setChapterId(chapter.getId());
            // 覆盖章节ID查找
            query.setChapterId(chapter.getId());
            List<LevelGroupDTO> list = baseMapper.findLevelList(query);
            if(!CollectionUtils.isEmpty(list)){
                group.setLevels(list);
                respList.add(group);
            }
        }

        return respList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<String> ids) {

        for(String id: ids){
            int count = quService.countByRepo(id);
            if(count > 0){
                Repo repo = this.getById(id);
                throw new ServiceException("题库："+repo.getTitle()+" 下面包含试题，无法删除！");
            }

            this.removeById(id);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String,Object> saveById(RepoDetailDTO reqDTO) {

        String tempId = reqDTO.getId();
        if(tempId.startsWith("temp_")){
            reqDTO.setId(null);
        }

        // 复制参数
        Repo entity = new Repo();
        BeanMapper.copy(reqDTO, entity);
        this.saveOrUpdate(entity);

        // 保存章节信息
        repoChapterService.saveAll(entity.getId(), reqDTO.getChapters());


        // 人员列表
        if(OpenType.PERSON.equals(entity.getOpenType())) {
            repoPersonService.modifyAll(tempId, entity.getId());
        }

        // 部门列表
        if(OpenType.DEPART.equals(entity.getOpenType())) {
            repoDepartService.saveAll(entity.getId(), reqDTO.getDeptCodes());
        }

        Map<String,Object> resp = new HashMap<>();
        resp.put("id", entity.getId());
        return resp;
    }
}
